<?php

namespace App\Modules\Package;


use App\Exceptions\StandardException;
use App\Library\Lock;
use App\Library\OSS;
use App\Modules\Coupon\Models\Coupon;
use App\Modules\Coupon\Models\UserCoupon;
use App\Modules\Order\Models\Order;
use App\Modules\Package\Models\GoodPackage;
use App\Modules\Package\Models\PackageAttr;
use App\Modules\Package\Models\PackageAttrValue;
use App\Modules\Package\Models\PackageSpec;
use App\Modules\User\Models\Member;
use App\Modules\User\Models\User;
use Carbon\Carbon;
use Facade\Ignition\Support\Packagist\Package;
use Illuminate\Support\Facades\DB;
use App\Modules\Coupon\Manager as CouponManager;
use Illuminate\Support\Facades\Log;
use Overtrue\LaravelWeChat\Facade as EasyWeChat;

class Manager
{
    public static function getPackage($id)
    {
        if (is_array($id)) {
            $package = GoodPackage::query()
                ->find($id)
                ->map(function ($item) {
                    foreach ($item as $tmp) {
                        if (!empty($item->hot_cover)) {
                            $item->hot_cover = OSS::instance()->getUrl($item->hot_cover);
                        }
                        if (!empty($item->recommend_cover)) {
                            $item->recommend_cover = OSS::instance()->getUrl($item->hot_cover);
                        }
                        if (!empty($item->selected_cover)) {
                            $item->selected_cover = OSS::instance()->getUrl($item->selected_cover);
                        }
                        $tmp->cover = OSS::instance()->getUrl($item->cover);
                        $tmp->order_cover = OSS::instance()->getUrl($item->order_cover);
                    }
                    return $item;
                });

        } else {
            /** @var GoodPackage $package */
            $package = GoodPackage::query()
                ->find($id);
            if (!is_null($package)) {
                $hotCover = null;
                $recommendCover = null;
                $selectedCover = null;
                if (!empty($package->hot_cover)) {
                    $package->hot_cover = OSS::instance()->getUrl($package->hot_cover);
                }
                if (!empty($package->recommend_cover)) {
                    $package->recommend_cover = OSS::instance()->getUrl($package->hot_cover);
                }
                if (!empty($package->selected_cover)) {
                    $package->selected_cover = OSS::instance()->getUrl($package->selected_cover);
                }
                $cover = [];
                foreach ($package->cover as $tmp) {
                    $cover[] = OSS::instance()->getUrl($tmp);
                }
                $package->order_cover = OSS::instance()->getUrl($package->order_cover);
                $package->cover = $cover;
            }

        }
        return $package;
    }

    public static function createOrder($user, $isPrepay, $packageId, $spec, $referrerId, $couponId = null, $param = [], $balanceParam = [])
    {
        return Lock::lock("order:{$user->id}", 2, function () use ($user, $isPrepay, $packageId, $spec, $referrerId, $couponId, $param, $balanceParam) {
            $package = self::getPackage($packageId);
            if ($package->status == GoodPackage::STATUS_OFF) {
                throw new StandardException('商品已下架');
            }
            $specId = array_column($spec, 'id');
            $packageSpec = PackageSpec::query()
                ->where('package_id', $packageId)
                ->whereIn('id', $specId)
                ->get()
                ->keyBy('id');
            if ($packageSpec->isEmpty()) {
                throw new StandardException("套系信息错误");
            }
            $service = [];
            foreach ($package->service as $item) {
                foreach ($item['value'] as $item2) {
                    $service[$item2['id']] = $item2;
                }
            }
            $spec = collect($spec)->keyBy('id');
            $defaultPrice = 0;
            PackageSpec::query()
                ->join('package_attr_values', 'package_attr_values.id', '=', 'package_specs.attr_value_id')
                ->where('package_specs.package_id', $packageId)
                ->where('package_specs.is_default', 1)
                ->each(function ($tmp) use (&$defaultPrice, $service) {
                    $defaultPrice += $tmp->selling_price * ($service[$tmp->id]['number'] ?? 0);
                });
            $attrValue = PackageAttrValue::query()
                ->whereIn('id', $packageSpec->pluck('attr_value_id')->all())
                ->get()
                ->keyBy('id');
            $attr = PackageAttr::query()
                ->whereIn('id', $attrValue->pluck('package_attr_id')->all())
                ->get()
                ->keyBy('id');
            DB::beginTransaction();
            $selectPrice = 0;
            Log::info("-------");
            $detail['spec'] = $packageSpec->map(function ($item) use (&$selectPrice, $attr, $attrValue, $spec) {
                $tmp = $attrValue->get($item->attr_value_id);
                $selectPrice += $tmp->selling_price * ($spec->get($item->id)['number'] ?? 0);
                return [
                    'id' => $item->id,
                    'attr' => $attr->get($tmp->package_attr_id)->name,
                    'attr_id' => $tmp->package_attr_id,
                    'attr_value_id' => $item->attr_value_id,
                    'attr_value' => $tmp->value,
                    'price' => $tmp->selling_price,
                    'discount' => $tmp->discount,
                    'is_default' => $item->is_default,
                    'cover' => OSS::instance()->getUrl($tmp->cover),
                    'number' => $spec->get($item->id)['number'],
                    'attr_sort' => $attr->get($tmp->package_attr_id)->sort,
                    'sort' => $tmp['sort'],
                ];
            })
                ->sortByDesc('sort')
                ->sortBy('id')
                ->sortByDesc('is_default')
                ->sortBy('attr_id')
                ->sortByDesc('attr_sort')
                ->values();

            $detail['default_price'] = $package->price;
            $price = $package->price - ($defaultPrice - $selectPrice);
            $detail['order_cover'] = $package->order_cover;
            $detail['is_free'] = $package->is_free;
            $detail['is_comment'] = 0;
            $referrer = null;
            if (!is_null($referrerId)) {
                $referrer = User::query()
                    ->where('id', $referrerId)
                    ->first();
            }
            $personal = null;
            if (!is_null($referrer) && $referrer->level == 2) {
                $personal = User::query()
                    ->where('level', '=', 3)
                    ->where('id', $referrer->personal_id)
                    ->first();
            }
            $discountAmount = 0;
            if (isset($param['has_discount'])) {
                $discountAmount = $package->getDiscount($price);
                if (!$discountAmount) {
                    $discountAmount = $package->getFullReduction($price);
                }
            }

            //余额支付
            $is_balance  = !empty($balanceParam['is_balance'])  ? $balanceParam['is_balance']  : 0;
            $balance_pay = !empty($balanceParam['balance_pay']) ? $balanceParam['balance_pay'] : 0;
            $order = Order::query()
                ->create([
                    'type'            => Order::TYPE_PACKAGE,
                    'shop_id'         => $package->shop_id,
                    'user_id'         => $user->id,
                    'pay_no'          => Order::getPayNo(),
                    'link_id'         => $packageId,
                    'title'           => $package->name,
                    'price'           => $isPrepay ? $package->prepay : max($price, 0),
                    'original_price'  => $price,
                    'detail'          => $detail,
                    'coupon_pay'      => 0,
                    'discount_amount' => $discountAmount,
                    'status'          => Order::STATUS_INIT,
                    'referrer_id'     => $referrerId,
                    'referrer_level'  => is_null($referrerId) ? null : $referrer->level,
                    'mobile'          => $param['mobile'] ?? null,
                    'name'            => $param['name'] ?? null,
                    'delivery'        => 0,
                    'address'         => $param['address'] ?? null,
                    'deliver_date'    => $param['deliver_date'] ?? null,
                    'cover'           => $package->order_cover,
                    'bill'            => $param['bill'] ?? null,
                    'personal_id'     => is_null($personal) ? null : $personal->id,
                    'final_payment'   => $isPrepay ? 0 : 1,
                    'is_prepay'       => $isPrepay,
                    'buyer_remark'    => isset($param['remark']) ? $param['remark'] : "",
                    'is_recharge'     => $package->is_recharge, //是否是充值商品（买多少返多少）
                    'is_balance'      => $is_balance,
                    'balance_pay'     => $balance_pay,
                ]);

            if (isset($param['has_discount'])) {
                $gift = $package->getGift();
                $order->update([
                    'gift' => $gift,
                ]);
            }
//            if (!is_null($couponId)) {
//                $coupon = UserCoupon::query()
//                    ->where('type', Coupon::TYPE_PACKAGE)
//                    ->where('id', $couponId)
//                    ->where('shop_id', $package->shop_id)
//                    ->where('user_id', $user->id)
//                    ->whereNull('use_id')
//                    ->where('price_limit', "<", $order->price)
//                    ->where('expiration_date', ">=", Carbon::now()->toDateString())
//                    ->where(function ($q) use($packageId) {
//                        return $q->whereNull('applicable')
//                            ->orWhereJsonContains('applicable', [(string) $packageId]);
//                    })
//                    ->first();
//                if (is_null($coupon)) {
//                    throw new StandardException("无效优惠券");
//                }
//                CouponManager::useCoupon($coupon, $order->id);
//                $order->coupon_pay = $coupon->money;
//                $order->save();
//            }
            DB::commit();
            return $order;
        });
    }

    public static function getMiniProgramCode(User $user, $poster)
    {
        $miniProgram = EasyWeChat::miniProgram();
        $response = $miniProgram->app_code->getUnlimit("" . $user->id . "#" . $poster->package_id . "#package", [
            'page' => "pages/product_detail/index",
            'width' => 136,
        ]);

        if ($response instanceof \EasyWeChat\Kernel\Http\StreamResponse) {
            $key = "mini_program" . "/" . $user->id . "/" . $poster->package_id . ".png";

            // $dir = 'D:/_project/php/wedding/public/mini_program' . "/" . $user->id . "/";
            // if (!file_exists($dir)) {
            //     mkdir($dir, 0777, true);
            // }
            // $file_path = 'D:/_project/php/wedding/public/mini_program' . "/" . $user->id . "/" . $poster->package_id . ".png";
            // file_put_contents($file_path, $response->getBody()->getContents());
            /** @var OSS $oss */
            $oss = OSS::instance();
            $oss->storeBinary($key, $response->getBody()->getContents());
            return $key;
        }
        return null;
    }
}
